package com.example.wxsmart.resources;

import com.alibaba.fastjson.JSON;
import com.example.wxsmart.pojo.Question;
import com.example.wxsmart.service.QuestionService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;

/**
 * @author Luojunxian
 * @data 2022/5/31 10:53
 * @classname ElasticSearchDocumentResources
 */
@Slf4j
@Component
public class ElasticSearchDocumentResources {

    @Resource
    private RestHighLevelClient client;

    @Resource
    private QuestionService questionService;

    @Value("${qa.index}")
    private String index;

    /**
     * 创建文档（全量更新）
     *
     * @param question 问题
     * @return {@code IndexResponse}
     */
    public IndexResponse createDocument(Question question) {
        IndexRequest indexRequest = new IndexRequest(index).id(String.valueOf(question.getId()));

        indexRequest.source(JSON.toJSONString(question), XContentType.JSON);

        try {
            IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);

            log.info("ElasticSearch:{}索引:id为{}的文档{}创建成功!",
                    index,
                    question.getId(),
                    question);

            return response;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取文档
     *
     * @param questionId 问题id
     * @return {@code Question}
     */
    public Question getDocument(Integer questionId) {
        GetRequest getRequest = new GetRequest(index, questionId.toString());

        try {
            GetResponse response = client.get(getRequest, RequestOptions.DEFAULT);

            return JSON.parseObject(response.getSourceAsString(), Question.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 更新文档
     * 更新文档(部分更新)
     *
     * @param question 问题
     * @return {@code UpdateResponse}
     */
    public UpdateResponse updateDocument(Question question) {
        UpdateRequest updateRequest = new UpdateRequest(index, question.getId().toString());

        updateRequest.doc(JSON.toJSONString(question), XContentType.JSON);

        try {
            return client.update(updateRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 删除文档
     *
     * @param idList id列表
     * @return {@code BulkResponse}
     * @throws IOException ioexception
     */
    public BulkResponse deleteDocument(List<Integer> idList) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();

        idList.forEach(id -> {
            DeleteRequest deleteRequest = new DeleteRequest(index, id.toString());
            bulkRequest.add(deleteRequest);
        });


        return client.bulk(bulkRequest, RequestOptions.DEFAULT);
    }

    /**
     * 批量导入文档
     *
     * @param list 列表
     * @return {@code BulkResponse}
     * @throws IOException ioexception
     */
    public BulkResponse batchDocument(List<Question> list) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();

        list.forEach(question -> {
            IndexRequest indexRequest = new IndexRequest(index).id(String.valueOf(question.getId()));
            indexRequest.source(JSON.toJSON(question).toString(), XContentType.JSON);
            bulkRequest.add(indexRequest);
        });

        return client.bulk(bulkRequest, RequestOptions.DEFAULT);
    }

    /**
     * 查询文档
     *
     * @param text 文本
     * @return {@code Question}
     */
    @Transactional(rollbackFor = Exception.class)
    public Question searchDocument(String text) {
        log.info("ElasticSearch:开始查找...");
        Question question = null;
        SearchRequest searchRequest = new SearchRequest(index);

        searchRequest
                .source()
                .query(QueryBuilders.matchQuery("question", text));

        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

            SearchHits searchHits = searchResponse.getHits();

            long total = searchHits.getTotalHits().value;

            // 如果搜索结果不为空,则为这条记录count加一
            if (total != 0) {
                SearchHit[] hits = searchHits.getHits();
                String sourceAsString = hits[0].getSourceAsString();
                question = JSON.parseObject(sourceAsString, Question.class);
                question.setCount(question.getCount() + 1);
                questionService.addOrUpdate(question);
            }
        } catch (IOException e) {
            log.info("ElasticSearch:查找失败,原因-->{}", e.getMessage());
        }

        return question;
    }
}
